﻿using System;
using System.Collections.Generic;
using TableDef;
using UnityEngine;
using UnityEngine.EventSystems;
/*
界面管理器
界面分为几个大层,现阶段只开放了10层，如果需要修改，改m_nLayerCounter即可

0: 战斗飘字，场景特效
1: 主界面，
2：对话界面
3, 弹出式界面
4, 通用信息条，显示金币，被弹出式界面呼出
5, 弹出式提示框层




每一小层panelbase的 RenderOrder 会以10为增量增长，这是为了给这个窗口里的 sortorder 预留的，子节点里如果加了sortorder脚本，其中填的参数order就是相对
父节点的renderorder的增量，这样保证每一个窗口里的层级显示正常。
每次需要跟新层次的时候，调用 DoResetWindow 来重新排序，保证层级的正确性
 
注意!!!!!
每个窗口的ondisable里不能调用开启和关闭其他窗口的操作，因为这个函数在release的时候会被调用，一旦操作别的窗口，会导致窗口逻辑序列里的数据混乱。


*/
namespace Share
{
    public enum SystemEventDef
    {
        System_Open_Window = -1000,
        System_Close_Window,
        System_LogError,
    }

    public partial class UIMgr : SingletonObject<UIMgr>
    {
        int m_nLayerOffsest = 1000; // 每大层的范围
        int m_nLayerCounter = 11; // 每小蹭的范围(第 11 层 为loading 层)
        ModifyBase m_Modify = new ModifyBase();
        // 窗口表数据结构
        //public class WindowDataDef : ResDataBase
        //{
        //    public string m_strWindowName;      // 窗口关键字
        //    public int m_nLayer;                // 所在层
        //    public int m_nToggleGroup;          // 所在互斥组,同组的界面同时只能显示一个
        //    public bool m_bPreload;             // 是否缓存
        //    public bool m_bCache;               // 是否关闭后保存
        //    public string m_strResPath;         // 资源路径


        //    protected override void OnInit()
        //    {
        //        m_nID = GetInt("id");
        //        m_strWindowName = GetString("panelName");
        //        m_nLayer = GetInt("Layer");
        //        m_strResPath = GetString("prefabPath");
        //        m_bPreload = GetBool("preload");
        //        m_nToggleGroup = GetInt("toggleGroup");
        //        m_bCache = GetBool("cache");

        //    }
        //}

        public enum UICameraType
        {
            Camera2d,
        }
        public enum LayerType
        {
            Main,
            AutoBattle,
            Normal,
            Navigation,
            PopWin,
            NetWin,
            Other
        }

        Dictionary<long, UICore> m_UIData = new Dictionary<long, UICore>();
        //Dictionary<string, WindowDataDef> m_TableData = new Dictionary<string, WindowDataDef>();

        [HideInInspector]
        public Camera m_uiCamera2d;  // 窗口摄像机
        public Camera m_uiCamera2dBack;  // 窗口摄像机,为透视摄像机
        [HideInInspector]
        public Camera m_uiCamera3d;  // 窗口摄像机,为透视摄像机
        [HideInInspector]
        public Transform m_UIRoot; // 窗口管理器的根节点

        static int GE_CC_RESORT_WINDOW = -1000;
        /// <summary>
        /// 初始化UI管理器
        /// </summary>
        protected override void OnInit()
        {
            for (int i = 0; i <= m_nLayerCounter; ++i)
            {
                m_UIData.Add(i, new UICore(i * m_nLayerOffsest));
            }
            ResDataMgr<t_windowdef>.Instance().DoLinkTxt("t_windowdef");
            if (m_UIRoot != null)
                return;
            EventMgr.Instance.AddListener(GE_CC_RESORT_WINDOW, OnResortWindow);
            // 界面用到的2d节点
            var root2d = GameObject.Find("UI2DRoot");
            if (root2d == null)
            {
                var root = ObjectMgr.Instance.CreateObj(UIConfig.Instance.UICameraProfabe);
                if (root == null)
                {
                    XKLog.LogError($"profab没有找到，致命错误");
                }
                else
                {
                    GameObject.DontDestroyOnLoad(root);
                    m_UIRoot = root.transform;
                    m_uiCamera2d = root.transform.Find("UICamera").GetComponent<Camera>();
                    m_uiCamera2d.enabled = true;
                }
                CameraMgr.Instance.SetUICamera(m_uiCamera2d);
                CameraMgr.Instance.DoFreshCamera();
            }
        }

        /// <summary>
        /// 根据窗口名称获取窗口配置数据
        /// </summary>
        /// <param name="windowName">窗口名称</param>
        /// <returns>窗口配置数据</returns>
        public t_windowdef GetTableDataByName(string windowName)
        {
            foreach (var item in GetAllResData())
            {
                if (item.m_strPanelName.Equals(windowName))
                    return item;
            }
            XKLog.Log("没有[" + windowName + "]的数据");
            return null;
        }

        public void ReloadTableData()
        {
            ResDataMgr<t_windowdef>.Instance().DoReload();
        }

        public void SetCameraDepath(int depth)
        {
            m_uiCamera2d.depth = depth;
        }

        // 窗口是否正在显示
        public bool IsWindowOpen(string strWindowName)
        {
            var win = GetWindowByName(strWindowName);
            if (win != null)
            {
                return win.IsShown;
            }
            return false;
        }


        public PanelBase GetWindowByName(string strWindowName)
        {
            foreach (var item in m_UIData)
            {
                var window = item.Value.GetWindow(strWindowName);
                if (window != null)
                    return window;
            }
            return null;
        }
        // 关闭指定大层的窗口
        // nLayer = -1 关闭所有层
        public void DoCloseAllWindowByLayer(int nLayer, bool bSave = true)
        {
            if (nLayer == -1)
            {
                foreach (var item in m_UIData)
                {
                    item.Value.DoCloseAll();
                }
            }
            else
            {
                if (m_UIData.Count > nLayer)
                    m_UIData[nLayer].DoCloseAll();
            }
        }



        /// <summary>
        /// 开启窗口，如果开着，就把参数穿进去
        /// </summary>
        /// <param name="strWindowName"></param>
        /// <param name="param"></param>
        public void DoOpenWindowExit(string strWindowName, EventParam param = null)
        {
            var data = GetTableDataByName(strWindowName);
            if (data != null)
            {
                m_UIData[data.m_nLayer].DoOpenWindowExit(strWindowName, param);
            }
        }
        // 对外接口,开启一个界面，
        // strWindowName window表里定义的这个窗口的名字， strParam 如果需要传进的参数，先用字符串，除非以后有特殊需求再改
        /// <summary>
        /// 打开指定窗口
        /// </summary>
        /// <param name="windowName">窗口名称</param>
        /// <param name="param">事件参数</param>
        /// <param name="onLoaded">加载完成回调</param>
        public void DoOpenWindow(string windowName, EventParam param = null, Action<PanelBase> onLoaded = null)
        {
            var data = GetTableDataByName(windowName);
            if (data != null)
            {
                m_UIData[data.m_nLayer].DoOpenWindow(windowName, param, (panel) =>
                {
                    onLoaded?.Invoke(panel);
                    m_Modify.MakeModify();

                });
            }
            else
            {
                XKLog.LogError($"表里没有填[{windowName}]这个窗口");
                onLoaded?.Invoke(null);
            }
        }


        //返回主界面，默认主界面是在第0层
        public void DoReturnMainUI()
        {
            foreach (var item in m_UIData)
            {
                if (item.Key == 0)
                    continue;
                item.Value.DoCloseAll();
            }
        }
        // 关闭指定互斥组的窗口
        public void DoCloseWindowByGroup(long nGroup, PanelBase exp)
        {
            if (nGroup < 0)
                return;
            foreach (var item in m_UIData)
            {
                item.Value.DoCloseWindowByGroup(nGroup, exp);
            }

        }
        //关闭窗口
        /// <summary>
        /// 关闭指定窗口
        /// </summary>
        /// <param name="windowName">窗口名称</param>
        public void DoCloseWindow(string windowName)
        {
            foreach (var item in m_UIData)
            {
                if (item.Value.DoCloseWindow(windowName))
                {
                    return;
                }
            }
            //刷新当前顶层窗口
        }


        // 预加载所有需要预加载的界面,这个放在进游戏的loading里做，选人界面和创建界面不需要
        public void DoPreloadWindow()
        {
            return;

        }



        PanelBase m_TopWindow = null;
        // 界面层级重新排序
        public void DoResortWindow()
        {
            //PanelBase topWindow = null;
            List<PanelBase> list = new List<PanelBase>();
            foreach (var item in m_UIData)
            {
                //刷新这一层的所有窗口叠加排序
                item.Value.DoResortWindow();

                //获取所有可见1全屏窗口
                item.Value.GetFullWindow(ref list);
            }

            // 把所有遮挡窗口都置为遮挡，只剩下最上面那个显示
            if (list.Count > 0)
            {
                for (int i = 0; i < list.Count; ++i)
                {
                    if (i == list.Count - 1)
                    {
                        list[i].DoTop();
                        m_TopWindow = list[i];
                    }
                    else
                        list[i].DoBeCover();
                }
                list[list.Count - 1].DoTop();
            }
        }


        /// <summary>
        /// 获取最顶端窗口
        /// </summary>
        /// <returns></returns>

        public PanelBase GetTopPanel()
        {
            return m_TopWindow;
        }


        bool OnResortWindow(int ge, EventParam parameter)
        {
            DoResortWindow();
            return true;
        }

        // 是否隐藏整个界面
        public void DoSetUIShow(bool bShow)
        {
            m_uiCamera2d.gameObject.SetActive(bShow);

        }

        public bool IsUIShow()
        {
            return m_uiCamera2d.gameObject.activeInHierarchy;
        }


        List<t_windowdef> GetAllResData()
        {
            return ResDataMgr<t_windowdef>.Instance().GetResData();
        }


        public void DoUpdate()
        {
            if (m_Modify.IsModify)
            {
                DoResortWindow();
                m_Modify.ClearModify();
            }
        }

        public void DoFreshSortWindow()
        {
            m_Modify.MakeModify();
        }

        /// <summary>
        /// 切换窗口状态（打开/关闭）
        /// </summary>
        /// <param name="windowName">窗口名称</param>
        public void DoToggleWindow(string windowName)
        {
            if (IsWindowOpen(windowName))
                DoCloseWindow(windowName);
            else
                DoOpenWindow(windowName);
        }

        public bool IsPointOverUI(Vector2 pos)
        {

            // 检查是否有UI元素在点击位置
            var pointerEventData = new PointerEventData(EventSystem.current)
            {
                position = pos
            };
            var results = new List<RaycastResult>();
            EventSystem.current.RaycastAll(pointerEventData, results);

            return results.Count > 0;
        }
    }
}
